package com.syh.jn.scm.infrastructure.repository.impl.supplier.stock;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AggregateRepoHibernateImplTmpl;
import com.syh.jn.scm.domain.supplier.entity.stock.StockOtherInBill;
import com.syh.jn.scm.domain.supplier.entity.stock.StockOtherInBillItem;
import com.syh.jn.scm.domain.supplier.repository.stock.StockOtherInBillRepository;
import com.syh.jn.scm.dto.supplier.stock.StockOtherInBillItemVo;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsBrandModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsCategoryModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsModel;
import com.syh.jn.scm.infrastructure.repository.model.stock.stockOtherInBill.StockOtherInBillItemModel;
import com.syh.jn.scm.infrastructure.repository.model.stock.stockOtherInBill.StockOtherInBillModel;
import lombok.extern.java.Log;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 其它出入库
 */
@Log
@Repository
public class StockOtherInBillRepositoryImpl implements StockOtherInBillRepository {

  private HibernateTemplate hibernateTemplate;

  private AggregateRepoHibernateImplTmpl<StockOtherInBill, StockOtherInBillModel, Long> stockOtherInBillRepoHibernateImpl;
  private AggregateRepoHibernateImplTmpl<StockOtherInBillItem, StockOtherInBillItemModel, Long> stockOtherInBillItemRepoHibernateImpl;

  @Autowired
  public StockOtherInBillRepositoryImpl(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
    this.stockOtherInBillRepoHibernateImpl =
            new AggregateRepoHibernateImplTmpl.Builder().hibernateTemplate(hibernateTemplate).idClass(Long.class).entityClass(StockOtherInBill.class).modelClass(StockOtherInBillModel.class).build();

    this.stockOtherInBillItemRepoHibernateImpl =
            new AggregateRepoHibernateImplTmpl.Builder().hibernateTemplate(hibernateTemplate).idClass(Long.class).entityClass(StockOtherInBillItem.class).modelClass(StockOtherInBillItemModel.class).build();

  }

  /**
   * 重写add方法
   *
   * @param stockOtherInBill
   * @return
   */
  @Override
  public Long add(StockOtherInBill stockOtherInBill) {
    //保存其他出库入单
    Long id = this.stockOtherInBillRepoHibernateImpl.add(stockOtherInBill).getId();
    //保存其他出入库单项
    this.saveItems(id, stockOtherInBill.getItems());
    return id;
  }

  /**
   * 重写update方法
   *
   * @param stockOtherInBill
   */
  @Override
  public void update(StockOtherInBill stockOtherInBill) {
    this.update(stockOtherInBill, true);
  }

  /**
   * 重载update方法,选择是否更新订单项
   *
   * @param stockOtherInBill
   * @param isUpdateItem
   */
  @Override
  public void update(StockOtherInBill stockOtherInBill, boolean isUpdateItem) {
    if (isUpdateItem) {
      this.delItemsById(stockOtherInBill.getId());
      this.saveItems(stockOtherInBill.getId(), stockOtherInBill.getItems());
    }
    this.stockOtherInBillRepoHibernateImpl.update(stockOtherInBill);

  }

  /**
   * 重写getById方法,默认包含item
   *
   * @param aLong
   * @return
   */
  @Override
  public StockOtherInBill getById(Long aLong) {
    StockOtherInBill stockOtherInBill = this.stockOtherInBillRepoHibernateImpl.getById(aLong);
    List<StockOtherInBillItem> stockOtherInBillItems = this.getItemsById(aLong);
    stockOtherInBill.setItems(stockOtherInBillItems);
    return stockOtherInBill;
  }

  /**
   * 一般使用orm框架实现 例如Hibenate 根据条件获取数据
   *
   * @param wrapper
   * @return
   */
  @Override
  public StockOtherInBill getOne(Wrapper wrapper) {
    return null;
  }

  @Override
  public List<StockOtherInBill> getList(Wrapper wrapper) {
    return stockOtherInBillRepoHibernateImpl.getList(wrapper);
  }

  @Override
  public List<StockOtherInBill> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return stockOtherInBillRepoHibernateImpl.findListPage(wrapper, startRow, count);
  }

  @Override
  public int getCount(Wrapper wrapper) {
    return stockOtherInBillRepoHibernateImpl.getCount(wrapper);
  }

  @Override
  public boolean contains(Long aLong) {
    return stockOtherInBillRepoHibernateImpl.contains(aLong);
  }

  public Query buildQuery(StringBuffer hql) {
    return stockOtherInBillRepoHibernateImpl.buildQuery(hql);
  }

  public Query buildQuery(String hql) {
    return stockOtherInBillRepoHibernateImpl.buildQuery(hql);
  }

  @Override
  public StockOtherInBill getById(Long id, boolean haveItems) {
    return haveItems ? this.getById(id) : this.stockOtherInBillRepoHibernateImpl.getById(id);
  }

  @Override
  public StockOtherInBillItem getItemByItemId(Long id) {
    return this.stockOtherInBillItemRepoHibernateImpl.getById(id);
  }

  /**
   * 重写removeById方法
   *
   * @param aLong
   */
  @Override
  public void removeById(Long aLong) {
    this.stockOtherInBillRepoHibernateImpl.removeById(aLong);
    this.delItemsById(aLong);
  }

  /**
   * 重写remove方法
   *
   * @param stockOtherInBill
   */
  @Override
  public void remove(StockOtherInBill stockOtherInBill) {
    this.stockOtherInBillRepoHibernateImpl.removeById(stockOtherInBill.getId());
    this.delItemsById(stockOtherInBill.getId());
  }

  @Override
  public List<StockOtherInBillItem> findStockOtherInBillItemListPage(Wrapper wrapper, Integer startRow, Integer count) {
    log.warning("该接口暂不实现");
    return Collections.EMPTY_LIST;
  }

  @Override
  public int findStockOtherInBillItemListPageCount(Wrapper wrapper) {
    return this.stockOtherInBillItemRepoHibernateImpl.getCount(wrapper);
  }

  /**
   * 根据服务商id删除采购单
   * @param businessEntityId
   */
  @Override
  public void deleteByBusinessEntityId(Long businessEntityId) {
    String itemHql = "delete from StockOtherInBillItemModel where businessEntityId = :businessEntityId";
    Query itemQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(itemHql);
    itemQuery.setParameter("businessEntityId",businessEntityId);
    itemQuery.executeUpdate();
    String orderHql = "delete from StockOtherInBillModel where businessEntityId = :businessEntityId";
    Query orderQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(orderHql);
    orderQuery.setParameter("businessEntityId",businessEntityId);
    orderQuery.executeUpdate();
  }

  @Override
  public List<StockOtherInBillItemVo> findStockOtherInBillItemVoByBillId(Long stockOtherInBillId) {
    log.warning("该接口暂不实现");
    return Collections.EMPTY_LIST;
  }

  @Override
  public List<StockOtherInBillItemVo> findStockOtherInBillItemVoListPage(Wrapper wrapper, Integer startRow, Integer count) {
    log.warning("该接口暂不实现");
    return Collections.EMPTY_LIST;
  }

  @Override
  public int findStockOtherInBillItemVoCount(Wrapper wrapper) {
    return this.stockOtherInBillItemRepoHibernateImpl.getCount(wrapper);
  }

  /**
   * 添加出入库单项
   *
   * @param id
   * @param stockOtherInBillItems
   */
  private void saveItems(Long id, List<StockOtherInBillItem> stockOtherInBillItems) {
    stockOtherInBillItems.forEach(stockOtherInBillItem -> {
      StockOtherInBillModel stockOtherInBillModel = this.hibernateTemplate.get(StockOtherInBillModel.class, id);
      stockOtherInBillItem.setStockOtherInBillId(id);
      stockOtherInBillItem.setBusinessEntityId(stockOtherInBillModel.getBusinessEntityId());
      GoodsModel goodsModel = this.hibernateTemplate.get(GoodsModel.class, stockOtherInBillItem.getGoodsId());
      GoodsBrandModel goodsBrandModel = new GoodsBrandModel();
      if (goodsModel.getGoodsBrandId() != null) {
        goodsBrandModel = this.hibernateTemplate.get(GoodsBrandModel.class, goodsModel.getGoodsBrandId());
      }
      GoodsCategoryModel goodsCategoryModel = new GoodsCategoryModel();
      if (goodsModel.getCategoryId() != null) {
        goodsCategoryModel = this.hibernateTemplate.get(GoodsCategoryModel.class, goodsModel.getCategoryId());
      }
      StockOtherInBillItemModel stockOtherInBillItemModel = new StockOtherInBillItemModel();
      ExtBeanUtils.copyProperties(stockOtherInBillItem, stockOtherInBillItemModel);
      //在仓储层冗余是为了安全和数据的准确
      stockOtherInBillItemModel.setGoodsName(goodsModel.getName());
      stockOtherInBillItemModel.setSpecName(goodsModel.getSpecName());
      stockOtherInBillItemModel.setGoodsCode(goodsModel.getCode());
      stockOtherInBillItemModel.setIsDefaultGoods(goodsModel.getIsDefaultGoods());
      stockOtherInBillItemModel.setConversionRate(goodsModel.getConversionRate());
      stockOtherInBillItemModel.setCodeBar(goodsModel.getCodeBar());
      stockOtherInBillItemModel.setUnits(goodsModel.getUnits());
      stockOtherInBillItemModel.setCategoryId(goodsModel.getCategoryId());
      stockOtherInBillItemModel.setCategoryName(goodsCategoryModel.getName());
      stockOtherInBillItemModel.setCategoryCatalogCode(goodsCategoryModel.getCatalogCode());
      stockOtherInBillItemModel.setGoodsBrandId(ExtStringUtils.isBlank(goodsModel.getGoodsBrandId()) ? null : goodsModel.getGoodsBrandId());
      stockOtherInBillItemModel.setGoodsBrandName(ExtStringUtils.isBlank(goodsBrandModel.getName()) ? null : goodsBrandModel.getName());
      this.hibernateTemplate.save(stockOtherInBillItemModel);

    });
  }

  /**
   * 删除出入库单项
   *
   * @param stockOtherInBillId
   */
  private void delItemsById(Long stockOtherInBillId) {

    String hql = "delete StockOtherInBillItemModel model WHERE model.stockOtherInBillId = :stockOtherInBillId";
    Query query = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(hql);
    query.setLong("stockOtherInBillId", stockOtherInBillId);
    query.executeUpdate();
  }

  /**
   * 根据出入库记录id获取出入库记录项
   *
   * @param stockOtherInBillId
   * @return
   */
  public List<StockOtherInBillItemModel> getItemsModleById(Long stockOtherInBillId) {
    //获取库存项
    String hql = "FROM StockOtherInBillItemModel model WHERE model.stockOtherInBillId = ?";
    List<StockOtherInBillItemModel> stockOtherInBillItemModels = (List<StockOtherInBillItemModel>) this.hibernateTemplate.find(hql, stockOtherInBillId);

    return stockOtherInBillItemModels;
  }

  /**
   * 根据出入库记录id获取出入库记录项
   *
   * @param stockOtherInBillId
   * @return
   */
  public List<StockOtherInBillItem> getItemsById(Long stockOtherInBillId) {
    //获取库存项
    List<StockOtherInBillItemModel> stockOtherInBillItemModels = this.getItemsModleById(stockOtherInBillId);
    List<StockOtherInBillItem> stockOtherInBillItems = new ArrayList<>();
    stockOtherInBillItemModels.forEach(stockOtherInBillItemModel -> {
      StockOtherInBillItem stockOtherInBillItem = new StockOtherInBillItem();
      ExtBeanUtils.copyProperties(stockOtherInBillItemModel, stockOtherInBillItem);
      stockOtherInBillItems.add(stockOtherInBillItem);
    });
    return stockOtherInBillItems;
  }

}
